package edu.ynu.se.xiecheng.achitectureclass.demo.service;

import edu.ynu.se.xiecheng.achitectureclass.common.service.LogicService;
import edu.ynu.se.xiecheng.achitectureclass.demo.config.HttpClientConfig;
import edu.ynu.se.xiecheng.achitectureclass.demo.dao.CameraDataDao;
import edu.ynu.se.xiecheng.achitectureclass.demo.dao.DeviceDao;
import edu.ynu.se.xiecheng.achitectureclass.demo.entity.data.CameraData;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.imageio.ImageIO;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

@Service
public class CameraDataService extends LogicService<CameraDataDao, CameraData, Long> {
    public CameraDataService(@Autowired CameraDataDao dao) {
        super(dao);
    }

    private static final String CAMERA_LOGIN_URL = "http://42.193.14.241:7000/ysapi/subAccount/getToken";
    private static final String CAMERA_CAPTURE_URL = "https://open.ys7.com/api/lapp/device/capture";
    private String accessToken;
    private long expireTime;
    @Autowired
    private HttpClientConfig httpClientConfig;
    @Autowired
    private DeviceDao deviceDao;

    public Map<String, String> getCameraToken(){
        if (accessToken != null && System.currentTimeMillis() < expireTime) {
            Map<String, String> tokenMap = new HashMap<>();
            tokenMap.put("access_token", accessToken);
            return tokenMap;
        }

        Map<String, String> params = new HashMap<>();
        params.put("accountId", "1ca7f0ab24ba41b291346347ec30140e");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, String>> request = new HttpEntity<>(params, headers);

        try {
            ResponseEntity<Map> response = httpClientConfig.restTemplate().postForEntity(CAMERA_LOGIN_URL, request, Map.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                Map<String, Object> responseBody = response.getBody();
                accessToken = (String) ((Map) responseBody.get("data")).get("accessToken");
                expireTime = (long) ((Map) responseBody.get("data")).get("expireTime");
                Map<String, String> tokenMap = new HashMap<>();
                tokenMap.put("access_token", accessToken);
                return tokenMap;
            } else {
                throw new RuntimeException("Failed to obtain access token: " + response.getStatusCode());
            }
        } catch (Exception e) {
            throw new RuntimeException("Error obtaining access token: " + e.getMessage());
        }
    }


    public Map<String, String> capture() {
        if (accessToken == null || System.currentTimeMillis() > expireTime) {
            getCameraToken();
        }
        MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
        params.add("accessToken", accessToken);
        params.add("deviceSerial", "AB9831171");
        params.add("channelNo", 1);
        params.add("quality", 0);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(params, headers);

        try {
            ResponseEntity<Map> response = httpClientConfig.restTemplate().postForEntity(CAMERA_CAPTURE_URL, request, Map.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                Map<String, Object> responseBody = response.getBody();
                Map<String, String> image = new HashMap<>();
                String picUrl = (String) ((Map)(responseBody.get("data"))).get("picUrl");
                URL url = new URL(picUrl);
                try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                    ImageIO.write(ImageIO.read(url), "png", os);
                    byte[] imageBytes = os.toByteArray();
                    String img = "data:image/png;base64," + Base64.encodeBase64String(imageBytes);

                    CameraData cameraData = new CameraData();
                    cameraData.setImageUrl(img);
                    cameraData.setDevice(deviceDao.findDeviceBySerialNumber("AB9831171"));
                    getDAO().save(cameraData);

                    image.put("picUrl", img);
                }catch (Exception e) {
                    e.printStackTrace();
                }
                return image;
            } else {
                throw new RuntimeException("Failed to obtain access token: " + response.getStatusCode());
            }
        } catch (Exception e) {
            throw new RuntimeException("Error obtaining access token: " + e.getMessage());
        }
    }
}